import random

from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django_redis import get_redis_connection

from utils.encrypt import md5
from utils.tencent.sms import send_sms_single
from web import models
from web.forms.bootstrap import BootStrapForm
from web.models import UserInfo


class RegisterModelForm( forms.ModelForm):
    # user_name = forms.CharField(required=False)

    mobile_phone = forms.CharField(label='手机号',validators=[
        RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$','手机号格式错误'),])

    passwd = forms.CharField(label='密码', min_length=8,max_length=64, error_messages={
         'required':'密码不能为空!','min_length':'密码过短!','max_length':'密码过长,意识挺好哈'}, widget=forms.PasswordInput())

    confirm_passwd = forms.CharField(label='重复密码',min_length=8,max_length=64, error_messages={
        'required':'密码不能为空!','min_length':'密码过短!','max_length':'密码过长,意识挺好哈'}, widget=forms.PasswordInput(
        attrs={'class':'form-control','placeholder':'请再次输入密码'}),)

    code = forms.CharField(label='验证码')



    class Meta:
        model = models.UserInfo
        #   原models里定义的顺序 加上上面的 RegisterModelForm中新增的顺序
        # fields = "__all__"

        # error_messages ={
        #     'user_name':{'required':'用户名已占用！'},
        #     'email':{'required':'用户名已占用！'},
        #
        # }
        # 重新自定义顺序
        fields = ['user_name','email','passwd','confirm_passwd','mobile_phone','code']

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)


    def clean_user_name(self):
        user_name = self.cleaned_data['user_name']
        # if user_name == 'jacky':
        #     raise ValidationError('Lao zi hai alive~')
        if UserInfo.objects.filter(user_name=user_name).exists():
            raise ValidationError('用户名已被占用')
        return  user_name

    def clean_email(self):
        email = self.cleaned_data['email']
        if UserInfo.objects.filter(email=email).exists():
            raise ValidationError('邮箱名已被占用')
        return email

    def clean_passwd(self):
        passwd = self.cleaned_data['passwd']
        return md5(passwd)#encrypt the passwd



    def clean_confirm_passwd(self):
        passwd = self.cleaned_data['passwd']
        confirm_passwd = md5(self.cleaned_data['confirm_passwd'])

        if passwd != confirm_passwd:
            raise ValidationError('两次密码不一致！')

        return confirm_passwd

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']

        # mobile_phone = self.cleaned_data['mobile_phone']

        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')

        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误，请重新输入')

        return code



# class Register_hook(forms.Form):



class SendSmsForm(forms.Form):
    # phone hook
    mobile_phone = forms.CharField(label='手机号',error_messages={'required':'手机号不能为空'},validators=[
    RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$','手机号格式错误'),])


    def __init__(self,request,*args, **kwargs):
        super().__init__(*args, **kwargs)#do father's init But it means nothing different bu now
        self.request = request




    def clean_mobile_phone(self):
        '''
        Hook of verify tel number
        @return:
        '''
        mobile_phone = self.cleaned_data['mobile_phone']

        #verify if the template of sms mesage translate by ajax is worng
        #request.GET.get('tpl')
        tpl = self.request.GET.get('tpl')

        template_id = settings.TEMPLATE_ID.get(tpl)
        if not template_id:
            # self.add_error('mobile_phone','模板错误') equal the next code but the program will go down not raise
            raise  ValidationError('模板错误')
        #verify if the num ajax input aleready exists
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == 'signin':
            if not exists:
                raise ValidationError('手机号不存在')
        else:
            # 校验数据库中是否已有手机号
            if exists:
                raise ValidationError('手机号已存在')

        # sen message and store the code in redis
        code = random.randrange(1000,9999)
        sms = send_sms_single(mobile_phone,template_id,[code,])
        print(sms)
        print(code)
        # wirte code in redis (django-redis)
        conn = get_redis_connection()
        conn.set(mobile_phone,code,ex=60)
        # print('it is ok!')
        return  mobile_phone


class LoginSmsForm(BootStrapForm ,forms.Form):
    mobile_phone = forms.CharField(label='手机号', error_messages={'required':'手机号不得为空'},validators=[
        RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    code = forms.CharField(
        label='验证码', error_messages={'required':'验证码不得为空'},
        widget=forms.TextInput()
        )



    # def __init__(self, *args, **kwargs):
    #     super().__init__(*args,**kwargs)

    #

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        # if not mobile_phone:
        #     raise ValidationError('手机号必须填！')
        if  not UserInfo.objects.filter(mobile_phone=mobile_phone).exists():
            raise  ValidationError('手机号不存在')

        return  mobile_phone

    def clean_code(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        code = self.cleaned_data['code']

        if not mobile_phone:
            return code
        # if not code:
        #     raise ValidationError('验证码不能为空！')

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')

        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误，请重新输入')
        return  code



class LoginForm(BootStrapForm, forms.Form):
    username = forms.CharField(label='用户名',error_messages={'required':'用户名不得为空'} )

    password = forms.CharField(
        label='密码',error_messages={'required':'密码不得为空'} ,
        widget=forms.PasswordInput()
        )
    code = forms.CharField(label='图片验证码')

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        return md5(pwd)

    def clean_code(self):
        """ 钩子 图片验证码是否正确？ """
        # 读取用户输入的yanzhengm
        code = self.cleaned_data['code']

        # 去session获取自己的验证码
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新获取')

        if code.strip().upper() != session_code.strip().upper():
            raise ValidationError('验证码输入错误')

        return code










